package org.hyperledger.fabric.sdk;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.spec.InvalidKeySpecException;
import java.util.LinkedList;
import java.util.List;

import org.hyperledger.fabric.sdk.aberic.ChaincodeManager;
import org.hyperledger.fabric.sdk.aberic.FabricConfig;
import org.hyperledger.fabric.sdk.aberic.bean.Chaincode;
import org.hyperledger.fabric.sdk.aberic.bean.Orderers;
import org.hyperledger.fabric.sdk.aberic.bean.Peers;
import org.hyperledger.fabric.sdk.exception.CryptoException;
import org.hyperledger.fabric.sdk.exception.InvalidArgumentException;
import org.hyperledger.fabric.sdk.exception.ProposalException;
import org.hyperledger.fabric.sdk.exception.TransactionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 用于应用层管理SDK的相关操作
 * 
 * @author LQ
 *
 */
public class FabricManager {

	public static void main(String[] args) throws CryptoException, InvalidArgumentException, NoSuchAlgorithmException,
	      NoSuchProviderException, InvalidKeySpecException, TransactionException, IllegalAccessException,
	      InstantiationException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IOException, ProposalException {
		ChaincodeManager manager2 = FabricManager.obtain().getManager();
		final List<String> argsList = new LinkedList<String>();
		final String fcn = "query";
		switch (fcn) {
		case "query":
			argsList.add("a");
			String[] arguments = new String[argsList.size()];
			argsList.toArray(arguments);
			manager2.query(fcn, arguments);
			break;
		default:
			break;
		}
	}

	private static final Logger log = LoggerFactory.getLogger(FabricManager.class);

	private ChaincodeManager manager;

	private static FabricManager instance = null;

	public static FabricManager obtain() throws CryptoException, InvalidArgumentException, NoSuchAlgorithmException,
	      NoSuchProviderException, InvalidKeySpecException, TransactionException, IOException, IllegalAccessException,
	      InstantiationException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException {
		if (null == instance) {
			synchronized (FabricManager.class) {
				if (null == instance) {
					instance = new FabricManager();
				}
			}
		}
		return instance;
	}

	private FabricManager() throws CryptoException, InvalidArgumentException, NoSuchAlgorithmException,
	      NoSuchProviderException, InvalidKeySpecException, TransactionException, IOException, IllegalAccessException,
	      InstantiationException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException {
		manager = new ChaincodeManager("Admin", getConfig());
	}

	/**
	 * 获取节点服务器管理器
	 * 
	 * @return 节点服务器管理器
	 */
	public ChaincodeManager getManager() {
		return manager;
	}

	/**
	 * 根据节点作用类型获取节点服务器配置
	 * 
	 * @param type
	 *           服务器作用类型（1、执行；2、查询）
	 * @return 节点服务器配置
	 */
	private FabricConfig getConfig() {
		FabricConfig config = new FabricConfig();
		config.setOrderers(getOrderers());
		config.setPeers(getPeers());
		config.setChaincode(
		      getChaincode("mychannel", "mycc", "github.com/hyperledger/fabric/chaincode/", "1.1"));
		config.setChannelArtifactsPath(getChannleArtifactsPath());
		config.setCryptoConfigPath(getCryptoConfigPath());
		return config;
	}

	private Orderers getOrderers() {
		Orderers orderer = new Orderers();
		orderer.setOrdererDomainName("example.com");
		orderer.addOrderer("orderer.example.com", "grpc://192.168.1.62:7050");
		//orderer.addOrderer("orderer1.example.com", "grpc://192.168.1.62:7050");
		//orderer.addOrderer("orderer2.example.com", "grpc://192.168.1.62:7050");
		return orderer;
	}

	/**
	 * 获取节点服务器集
	 * 
	 * @return 节点服务器集
	 */
	private Peers getPeers() {
		Peers peers = new Peers();
		peers.setOrgName("Org1");
		peers.setOrgMSPID("Org1MSP");
		peers.setOrgDomainName("org1.example.com");
		peers.addPeer("peer1.org1.example.com", "peer1.org1.example.com", "grpc://192.168.1.62:7050", "grpc://192.168.1.62:7051",
		      "http://192.168.1.62:7054");
		return peers;
	}

	/**
	 * 获取智能合约
	 * 
	 * @param channelName
	 *           频道名称
	 * @param chaincodeName
	 *           智能合约名称
	 * @param chaincodePath
	 *           智能合约路径
	 * @param chaincodeVersion
	 *           智能合约版本
	 * @return 智能合约
	 */
	private Chaincode getChaincode(String channelName, String chaincodeName, String chaincodePath,
	      String chaincodeVersion) {
		Chaincode chaincode = new Chaincode();
		chaincode.setChannelName(channelName);
		chaincode.setChaincodeName(chaincodeName);
		chaincode.setChaincodePath(chaincodePath);
		chaincode.setChaincodeVersion(chaincodeVersion);
		// chaincode.setInvokeWatiTime(100000);
		chaincode.setTransactionWaitTime(100000);
		chaincode.setDeployWaitTime(120000);
		return chaincode;
	}

	/**
	 * 获取channel-artifacts配置路径
	 * 
	 * @return /WEB-INF/classes/fabric/channel-artifacts/
	 */
	private String getChannleArtifactsPath() {
		String directorys = FabricManager.class.getClassLoader().getResource("fabric").getFile();
		log.debug("directorys = " + directorys);
		File directory = new File(directorys);
		log.debug("directory = " + directory.getPath());

		return directory.getPath() + "/channel-artifacts/";
	}

	/**
	 * 获取crypto-config配置路径
	 * 
	 * @return /WEB-INF/classes/fabric/crypto-config/
	 */
	private String getCryptoConfigPath() {
		String directorys = FabricManager.class.getClassLoader().getResource("fabric").getFile();
		log.debug("directorys = " + directorys);
		File directory = new File(directorys);
		log.debug("directory = " + directory.getPath());

		return directory.getPath() + "/crypto-config/";
	}

}